题目链接
某地区经过对城镇交通状况的调查,得到现有城镇间快速道路的统计数据,并提出“畅通工程”的目标:使整个地区任何两个城镇间都可以实现快速交通(但不一定有直接的快速道路相连,只要互相间接通过快速路可达即可)。现得到城镇道路统计表,表中列出了任意两城镇间修建快速路的费用,以及该道路是否已经修通的状态。现请你编写程序,计算出全地区畅通需要的最低成本。
输入格式:
输入的第一行给出村庄数目N (1≤N≤100);随后的N(N−1)/2行对应村庄间道路的成本及修建状态:每行给出4个正整数,分别是两个村庄的编号(从1编号到N),此两村庄间道路的成本,以及修建状态 — 1表示已建,0表示未建。
输出格式:
输出全省畅通需要的最低成本。
输入样例:
4
1 2 1 1
1 3 4 0
1 4 1 1
2 3 3 0
2 4 2 1
3 4 5 0
输出样例:
3
第一种:结构体加并查集
#include<iostream>
#include<algorithm>
#include<cstdio>
using namespace std;
typedef struct Node{
int mt1;
int mt2;
int fee;
int sense;
}Node;
Node e[10001];
int f[101];
bool cmp(Node a,Node b){
return a.fee < b.fee;
}
void init(int n){
for(int i = 1;i <= n;i++)
f[i] = i;
return;
}
int getf(int x){
if(f[x] == x)
return x;
f[x] = getf(f[x]);
return f[x];
}
int merge(int a,int b){
int tx = getf(a);
int ty = getf(b);
if(tx != ty){
f[ty] = tx;
return 1;
}
return 0;
}
int main(){
int n, sm = 0,cnt = 0;
scanf("%d",&n);
int m = n * (n - 1) / 2;
for(int i = 0;i < m;i++)
scanf("%d%d%d%d",&e[i].mt1,&e[i].mt2,&e[i].fee,&e[i].sense);
sort(e,e + m,cmp);//默认权值从小到大对边进行排序
init(n);//初始化
//优先访问已经修建过的,因为已经修建过的花费的费用为0!!!!!前者之鉴,后事之师
for(int i = 0;i < m;i++)
if(e[i].sense==1)
merge(e[i].mt1,e[i].mt2)==1 ? cnt++ : cnt;
for(int i = 0; i< m;i++){//从小到大枚举每一条边
if(merge(e[i].mt1,e[i].mt2)){
if(!e[i].sense)
sm += e[i].fee;
cnt++;//计数器
}
if(cnt == n - 1)//知道选用了 n - 1条边
break;
}
printf("%d\n",sm);
return 0;
}
第二种优先队列加并查集
#include<bits/stdc++.h>
using namespace std;
struct Node{
long long v1,v2,fee;
bool friend operator < (Node a,Node b){
return a.fee > b.fee;
}
Node(int vv1 = 0,int vv2 = 0,int f = 0) : v1(vv1),v2(vv2),fee(f){}
}p;
int n,a,b,c,d,k,sum,f[105];
priority_queue <Node> q;
int getf(int x){
return x == f[x] ? x : f[x] = getf(f[x]);
}
int merge(int x,int y){
int tx = getf(x);
int ty = getf(y);
if(tx != ty){
f[ty] = tx;
return 0;
}
return 1;
}
int main(){
cin >> n;
for(int i = 1;i <= n;i++){
f[i] = i;
}
for(int i = 0;i < n * (n - 1) / 2;i++){
cin >> a >> b >> c >> d;
if(d == 1){
merge(a,b);
}
else{
q.push(Node(a,b,c));
}
}
sum = 0;
while(!q.empty()){
p = q.top();
q.pop();
if(merge(p.v1,p.v2) == 1){//!!!如果p.v1和p.v2已经通过别的点间接连接,那么就不需要在连接!!!
continue;
}
sum += p.fee;
k = 0;
for(int i = 1;i <= n;i++){
if(f[i] == i){
k++;
}
}
if(k == 1){
cout << sum << endl;
return 0;
}
}
cout << 0 << endl;
return 0;
}